home *** CD-ROM | disk | FTP | other *** search
- /* "Dumb terminal" mailbox interface
- * Copyright 1991 Phil Karn, KA9Q
- *
- * May '91 Bill Simpson
- * move to separate file for compilation & linking
- * Sep '91 Bill Simpson
- * minor changes for DTR & RLSD
- * Jan '93 Doug Crompton
- * Mods to code to make it work with both terminal
- * and Modem. Timers and CD check revamped. Now Always
- * detects CD loss and timeouts work properly.
- * Setting Tiptimeout to 0 disables idle and CD loss check
- *
- * Command Syntax now : 'start tip <interface> <modem|terminal>'
- */
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "timer.h"
- #include "proc.h"
- #include "iface.h"
- #ifndef UNIX
- #include "i8250.h"
- #endif
- #include "asy.h"
- #include "socket.h"
- #include "usock.h"
- #include "telnet.h"
- #include "mailbox.h"
- #include "tipmail.h"
- #include "devparam.h"
-
- #ifdef TIPMAIL
- #ifdef ALLSERV
-
- static void tip_in __ARGS((int dev,void *n1,void *n2));
- static void tipidle __ARGS((void *t));
-
- unsigned Tiptimeout = 180; /* Default tip inactivity timeout (seconds) */
-
- struct suspended {
- struct iface *ifp;
- unsigned timeout;
- char modem;
- } Tipsuspended[ASY_MAX];
-
- /* Input process */
- static void
- tip_in(dev,n1,n2)
- int dev;
- void *n1,*n2;
- {
- struct tipcb *tip;
- struct mbuf *bp;
- char *buf[2], line[MBXLINE];
- int c, ret, pos = 0;
-
- tip = (struct tipcb *) n1;
- while((c = get_asy(dev)) != -1){
- tip->firstwarn=1;
- tip->timeout=tip->default_timeout;
- Asy[dev].iface->lastrecv = secclock();
-
- if (!tip->raw) {
- c &= 0x7f;
- ret = 0;
- if(tip->echo == WONT){
- switch(c){
- case 18: /* CTRL-R */
- bp = pushdown(qdata(line,pos),4);
- #ifndef TNOS_68K
- memcpy(bp->data,"^R\r\n",4);
- #else
- memcpy(bp->data,"^R\r\l",4);
- #endif
- ret = 1;
- break;
- case 0x7f: /* DEL */
- case '\b':
- bp = NULLBUF;
- if(pos){
- --pos;
- bp = qdata("\b \b",3);
- }
- ret = 1;
- break;
- #ifndef TNOS_68K
- case '\r':
- #else
- case '\l':
- #endif
- c = '\n'; /* CR => NL */
- case '\n':
- #ifndef TNOS_68K
- bp = qdata("\r\n",2);
- #else
- bp = qdata("\r\l",2);
- #endif
- break;
- default:
- bp = pushdown(NULLBUF,1);
- *bp->data = c;
- break;
- }
- asy_send(dev,bp);
- tip->iface->lastsent = secclock();
- if(ret)
- continue;
- }
- line[pos++] = c;
- if(pos == MBXLINE - 1 || tip->echo == WILL
- || c == '\n'){
- line[pos] = '\0';
- pos = 0;
- usputs(tip->s,line);
- usflush(tip->s);
- }
- } else {
- usputc(tip->s,c);
- usflush(tip->s);
- }
- }
- /* get_asy() failed, terminate */
- close_s(tip->s);
- tip->in = tip->proc;
- tip->proc = Curproc;
- buf[1] = Asy[dev].iface->name;
- tip0(2,buf,NULL);
- }
- /* Start mailbox on serial line */
- int
- tipstart(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct iface *ifp;
- register struct asy *ap;
- register struct tipcb *tip;
- struct mbuf *bp, *dp, *op; /* op is output, dp is duplicate */
- struct fifo *fp;
- char *buf[2];
- int dev, c, i, off, cnt, cmd, s[2], type = TIP;
-
- if((ifp = if_lookup(argv[1])) == NULLIF){
- tprintf(Badinterface,argv[1]);
- return 1;
- }
- for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
- if(ap->iface == ifp)
- break;
- if(dev == ASY_MAX){
- tprintf("Interface %s not asy port\n",argv[1]);
- return 1;
- }
- if(ifp->raw == bitbucket){
- tprintf("Tip session already active on %s\n",argv[1]);
- return 1;
- }
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"Mbox tip");
- tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
-
- if (argc > 2 && *argv[2] == 'm')
- tip->modem = 1;
- tprintf("Tip started on %s - with%s CD check - ",argv[1], (tip->modem) ? "" : "out");
- tip->default_timeout = (argc > 3) ? atoi(argv[3]) : Tiptimeout;
- if (tip->default_timeout)
- tprintf("%d Second",tip->default_timeout);
- else
- tprintf("No");
- tprintf(" Timeout\n");
-
-
- /* Save output handler and temporarily redirect output to null */
- tip->asy_dev=dev;
- tip->rawsave = ifp->raw;
- ifp->raw = bitbucket;
- tip->iface = ifp;
- tip->proc = Curproc;
- tip->timer.func = tipidle;
- tip->timer.arg = (void *) tip;
- tip->raw=0;
- tip->next = Tiplist;
- Tiplist = tip;
- buf[1] = ifp->name;
-
- /* Suspend packet input drivers */
- suspend(ifp->rxproc);
-
- for(;;) {
- ifp->ioctl(ifp,PARAM_UP,TRUE,0L);
- /* Wait for DCD to be asserted if modem */
- if (tip->modem) {
- mspause (1000);
- while (! carrier_detect(tip->asy_dev))
- pwait(NULL);
- mspause(1000L);
- }
-
- if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
- tprintf("Could not create socket pair, errno %d\n",errno);
- tip0(2,buf,p);
- return 1;
- }
- seteol(s[0],"\n");
- seteol(s[1],"\n");
- tip->echo = WONT;
- tip->s = s[0];
- if (tip->modem)
- log(tip->s,"Phone Mailbox Login");
- newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,(void *)tip,0);
-
- /* check for line idle timeout and CD failure */
- tip->firstwarn=1;
- tip->timeout=tip->default_timeout;
- set_timer(&tip->timer,1000L);
- start_timer(&tip->timer);
-
- setflush(tip->s,-1);
- sockmode(tip->s,SOCK_ASCII);
-
- /* Now fork into two paths, one rx, one tx */
- /* first clear (ignore) junk in asyinc input
- which is always receiving - modem can garbage
- on disconnect
- */
- fp = &ap->fifo;
- fp->wp = fp->rp = fp->buf;
- fp->cnt = 0;
-
- tip->in = newproc("Mbox tip in",
- 256,tip_in,dev,(void *)tip,NULL,0);
- while((cnt = recv_mbuf(tip->s,&bp,0,NULL,0)) != -1) {
- if(!tip->raw) {
- dup_p(&dp,bp,off=0,cnt); /* dup the whole pkt to pull */
- for (i=0; i<cnt; i++)
- switch(PULLCHAR(&dp)) {
- case IAC: /* ignore most telnet options */
- dup_p(&op,bp,off,i-off);
- asy_send(dev,op);
- ifp->lastsent = secclock();
-
- if((cmd = ++i < cnt ? PULLCHAR(&dp) :
- recvchar(tip->s)) == -1)
- break;
- if(cmd > 250 && cmd < 255) {
- if((c = ++i < cnt ? PULLCHAR(&dp) :
- recvchar(tip->s)) == -1)
- break;
- switch(cmd){
- case WILL:
- if(c == TN_ECHO) {
- tip->echo = cmd;
- cmd = DO;
- }
- else
- cmd = DONT;
- break;
- case WONT:
- if(c == TN_ECHO)
- tip->echo = cmd;
- cmd = DONT;
- break;
- case DO:
- case DONT:
- cmd = WONT;
- break;
- }
- usprintf(tip->s,"%c%c%c",IAC,cmd,c);
- usflush(tip->s);
- }
- off = i + 1;
- break;
- case '\r':
- if ( ++i < cnt && /* Skip NL but not IAC */
- (PULLCHAR(&dp) == IAC)) {
- dp = pushdown(dp,1);
- *dp->data = IAC;
- }
- break;
- #ifndef TNOS_68K
- case '\n':
- #else
- case '\l':
- #endif
- dup_p(&op,bp,off,i-off);
- #ifndef TNOS_68K
- append(&op,qdata("\r\n",2));
- #else
- append(&op,qdata("\r\l",2));
- #endif
- asy_send(dev,op);
- ifp->lastsent = secclock();
- off = i + 1;
- break;
- }
-
- (void)pullup(&bp,NULLBUF,off);
- asy_send(dev,bp);
- } else {
- asy_send(dev,bp);
- }
- ifp->lastsent = secclock();
-
- pwait(NULL);
- }
- stop_timer(&tip->timer);
- mspause(2000L);
- close_s(tip->s);
- killproc(tip->in);
- tip->in = NULLPROC;
-
- pwait(itop(s[1])); /* let mailbox terminate, if necessary */
-
- if (!tip->keep && tip->modem) {
- /* Tell line to go down */
- ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
- mspause (5000);
- }
- }
- }
- int
- tip0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct iface *ifp;
- struct tipcb *tip, *prev = NULLTIP;
- struct proc *proc;
-
- if((ifp = if_lookup(argv[1])) == NULLIF){
- tprintf(Badinterface,argv[1]);
- return 1;
- }
- for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
- if(tip->iface == ifp) {
- if(prev != NULLTIP)
- prev->next = tip->next;
- else
- Tiplist = tip->next;
- proc = tip->proc;
- close_s(tip->s);
- ifp->raw = tip->rawsave;
- resume(ifp->rxproc);
- stop_timer(&tip->timer);
- killproc(tip->in);
- free((char *)tip);
- killproc(proc);
- return 0;
- }
- return 0;
- }
- static void
- tipidle(t)
- void *t;
- {
- struct tipcb *tip;
- #ifndef TNOS_68K
- static char *msg1 = "Line idle - One minute to disconnect...\007\r\n";
- static char *msg2 = "Disconnecting...\007\r\n";
- #else
- static char *msg1 = "Line idle - One minute to disconnect...\007\r\l";
- static char *msg2 = "Disconnecting...\007\r\l";
- #endif
- tip = (struct tipcb *) t;
-
- if (tip->modem && ! carrier_detect(tip->asy_dev)) {
- close_s(tip->s);
- return;
- }
-
- if (tip->default_timeout && --tip->timeout <= 0) {
- if (tip->firstwarn) {
- tip->iface->lastsent = secclock();
- asy_send(tip->iface->dev,qdata(msg1,strlen(msg1)));
- tip->timeout=60;
- start_timer(&tip->timer);
- tip->firstwarn=0;
- } else {
- asy_send(tip->iface->dev,qdata(msg2,strlen(msg2)));
- close_s(tip->s);
- }
- } else {
- start_timer(&tip->timer);
- }
- }
-
-
-
-
- void
- suspendTipMail(m)
- struct mbx *m;
- {
- char *args[2];
- register int k;
- register struct tipcb *tip;
-
- if (m->tip->modem) { /* if modem connect, we can resume */
- /* save the interface in the suspended array, for asytimer() */
- Tipsuspended[m->tip->asy_dev].ifp = m->tip->iface;
- Tipsuspended[m->tip->asy_dev].modem = m->tip->modem;
- Tipsuspended[m->tip->asy_dev].timeout = m->tip->default_timeout;
- m->tip->keep = 1;
- tputs ("Tipmail will resume after you disconnect\n");
- } else
- tputs ("Tipmail terminated on this interface\n");
- usflush (Curproc->output);
- /* now stop the tipmail */
- args[1] = m->tip->iface->name;
- tip0 (2, args, NULL);
- }
- #endif /*ALLSERV*/
- #endif /* TIPMAIL */
-
- static int Stelnet = -1;
-
- /* Start up Telnet server */
- int
- telnet1(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (installserver (argc, argv, &Stelnet, "Telnet listener", IPPORT_TELNET,
- "mbox", mbx_incom,2048, (void *)TELNET_LINK));
- }
- /* Stop telnet server */
- int
- telnet0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (deleteserver (&Stelnet));
- }
-
-
-